
{INCLUDE FILE UDRAW2 -- IMPLEMENTATION OF UDRAW}
{Copyright 1983, 1984, Apple Computer, Inc.}


{changed 05/01 1503 Changes to allow people to use Clascal on the Workshop}

{Segments: SgABCini(tialize and Terminate), SgDRWres(ident), SgABCc(o)ld, SgABCdbg}

{$IFC fRngDraw}
{$R+}
{$ELSEC}
{$R-}
{$ENDC}

{$IFC fSymDraw}
{$D+}
{$ELSEC}
{$D-}
{$ENDC}

    CONST
        magicNumber     =   32768;

    VAR fontID: TFontIDArray;

{$S SgDRWres}


{$S SgABCini}
PROCEDURE TrmntExceptionHandler;
    VAR ch:     CHAR;
        error:  INTEGER;
BEGIN
    IF onDesktop THEN
        ImDying; {This must be done first}

    IF NOT amDying THEN
        BEGIN
        {$IFC fDbgDraw}
        WriteLn('TrmntExceptionHandler');
        {$ENDC}
        amDying := TRUE;
        IF crashPad <> NIL THEN
            crashPad.Crash;
        END;

    {$IFC fDbgDraw}
 {Flush the input queue in case there was user typeahead to the alternate screen}
    WHILE KeyPress DO
        Read(ch);
    {$ENDC}

    IF NOT onDesktop THEN
        MoveConsole(error, mainscreen);
END;
{$S SgDRWres}


{$S SgABCini}
PROCEDURE QkDrError(error: INTEGER);
BEGIN
    {$IFC fDbgDraw}
    ABCbreak('QkDrError', error);
    {$ENDC}
    HALT;
END;
{$S SgDRWres}


{$S SgABCini}
PROCEDURE InitQDWM;
    VAR error:	        INTEGER;
        workDir:        Pathname;
        bootVol:        e_name;
        bootDir:        Pathname;
{$IFC LibraryVersion < 30}
        bootPort:       tports;
{$ENDC}
BEGIN
    {$IFC libraryVersion <= 20}
    InitGraf(@thePort, @QkDrError);
    {$ELSEC}
    InitGraf(@thePort);
    {$ENDC}

    crashPad := NIL;

    IF onDesktop THEN
        BEGIN
        OpenWM;
        SetPort(deskPort);
        wmIsInitialized := TRUE;
        END
    ELSE
        BEGIN
        {move WriteLns to alternate screen}
        MoveConsole(error, alscreen);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('MoveConsole error', error);
{$ENDC}

        { set work directory to boot volume for FMOpen}
        Get_Working_Dir(error, workDir);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('Get_Working_Dir error', error);
{$ENDC}

{$IFC LibraryVersion < 30}
        bootPort := OSBootVol(error);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('OSBootVol error', error);
{$ENDC}

        Get_Config_Name(error, bootPort, bootVol);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('Get_Config_Name error', error);
{$ENDC}
{$ELSEC}
        OSBootVol(error, bootVol);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('OSBootVol error', error);
{$ENDC}
{$ENDC}
        bootDir := CONCAT('-', bootVol);

        Set_Working_Dir(error, bootDir);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('Set_Working_Dir to boot vol error', error);
{$ENDC}

        FMOpen(error);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('FMOpen error = ', error);
{$ENDC}

        { Set work directory back after OpenWM }
        Set_Working_Dir(error, workDir);
{$IFC fDbgDraw}
        IF error > 0 THEN
            ABCBreak('Set_Working_Dir back to prefix error = ', error);
{$ENDC}
        END;
END;
{$S SgDRWres}


{$S SgABCdbg}
FUNCTION  BindHeap(activeVsClip, doBind: BOOLEAN): THeap;
BEGIN
    IF crashPad = NIL THEN
        BindHeap := NIL	    {no UABC to do it for me}
    ELSE
        BindHeap := crashPad.BindHeap(activeVsClip, doBind);
END;
{$S SgDRWres}


{$S SgABCcld}
FUNCTION  FilerReason(error: INTEGER): FReason;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    FilerReason := allOk;
    IF error > 0 THEN
        CASE error OF
             309:       FilerReason := noDiskSpace;
             315:       FilerReason := noMemory;
            4001:       FilerReason := badData;
            OTHERWISE   FilerReason := internalError;
            END;
END;
{$S SgDRWres}


{$S SgABCini}
PROCEDURE InitErrorAbort(error: INTEGER);
BEGIN
    IF error > 0 THEN
        BEGIN
        {$IFC fDbgDraw}
        ABCbreak('InitErrorAbort', error);
        {$ENDC}
        IF onDesktop THEN
            TellFiler(error, initFailed, FilerReason(error), NIL);
        HALT;
        END
    ELSE
    IF wmIsInitialized THEN
        IF Abort THEN
            BEGIN
            IF onDesktop THEN
                TellFiler(error, initFailed, aUserAbort, NIL);
            HALT;
            END;
END;
{$S SgDRWres}


{$S SgDRWres}
PROCEDURE Reduce(VAR numerator, denominator: INTEGER);	    {reduce fraction to lowest terms}
    VAR factor: INTEGER;
        maxFactor: INTEGER; {also makes cosmetics}
        smallerNumerator:   INTEGER;
        smallerDenominator: INTEGER;
BEGIN {very crude at the moment}
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    maxFactor := MIN(numerator, denominator);
    FOR factor := maxFactor DOWNTO 2 DO
        BEGIN
        smallerNumerator := numerator DIV factor;
        smallerDenominator := denominator DIV factor;
        IF (factor * smallerNumerator = numerator) AND (factor * smallerDenominator = denominator) THEN
            BEGIN
            numerator := smallerNumerator;
            denominator := smallerDenominator;
            END;
        END;
END;


{$S SgDRWres}
FUNCTION  FPtPlusPt(operand1, operand2: Point): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h + operand2.h;
    result.v := operand1.v + operand2.v;
    FPtPlusPt := LONGINT(result);
END;


{$S SgDRWres}
FUNCTION  FPtMinusPt(operand1, operand2: Point): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h - operand2.h;
    result.v := operand1.v - operand2.v;
    FPtMinusPt := LONGINT(result);
END;


{$S SgABCdat}
FUNCTION  FPtMulInt(operand1: Point; operand2: INTEGER): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h * operand2;
    result.v := operand1.v * operand2;
    FPtMulInt := LONGINT(result);
END;


{$S SgABCdat}
FUNCTION  FPtDivInt(operand1: Point; operand2: INTEGER): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h DIV operand2;
    result.v := operand1.v DIV operand2;
    FPtDivInt := LONGINT(result);
END;


{$S SgDRWres}
FUNCTION  FPtMaxPt(operand1, operand2: Point): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := Max(operand1.h, operand2.h);
    result.v := Max(operand1.v, operand2.v);
    FPtMaxPt := LONGINT(result);
END;


{$S SgDRWres}
FUNCTION  FPtMinPt(operand1, operand2: Point): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := Min(operand1.h, operand2.h);
    result.v := Min(operand1.v, operand2.v);
    FPtMinPt := LONGINT(result);
END;


{$S SgDRWres}
FUNCTION  FDiagRect(operand1: Rect): LONGINT;
    VAR result: Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.right - operand1.left;
    result.v := operand1.bottom - operand1.top;
    FDiagRect := LONGINT(result);
END;


{$S SgABCdat}
PROCEDURE BoolToStr(bool: BOOLEAN; str: TPstring);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF bool THEN
        str^ := 'TRUE'
    ELSE
        str^ := 'FALSE';
END;


FUNCTION  LIntDivLInt(i, j: LONGINT): LONGINT;
    EXTERNAL;


FUNCTION  LIntDivInt(i: LONGINT; j: INTEGER): LONGINT;
    EXTERNAL;


FUNCTION  LIntMulInt(i: LONGINT; j: INTEGER): LONGINT;
    EXTERNAL;


{$S SgDRWres}
FUNCTION  LIntOvrInt(i: LONGINT; j: INTEGER): LONGINT;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF i>0 THEN
        LIntOvrInt := LIntDivInt(i+(j DIV 2), j)
    ELSE
        LIntOvrInt := LIntDivInt(i-(j DIV 2), j);
END;


{$S SgABCdat}
PROCEDURE PtPlusPt(operand1, operand2: Point; VAR result: Point);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h + operand2.h;
    result.v := operand1.v + operand2.v;
END;


{$S SgABCdat}
PROCEDURE PtMinusPt(operand1, operand2: Point; VAR result: Point);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h - operand2.h;
    result.v := operand1.v - operand2.v;
END;


{$S SgABCdat}
PROCEDURE PtMulInt(operand1: Point; operand2: INTEGER; VAR result: Point);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h * operand2;
    result.v := operand1.v * operand2;
END;


{$S SgABCdat}
PROCEDURE PtDivInt(operand1: Point; operand2: INTEGER; VAR result: Point);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h DIV operand2;
    result.v := operand1.v DIV operand2;
END;


{$IFC LibraryVersion <= 20}
FUNCTION  EqualPt(operand1, operand2: Point): BOOLEAN;
BEGIN
    EqualPt := (operand1.h = operand2.h) AND (operand1.v = operand2.v);
END;
{$ENDC}


{$S SgDRWres}
PROCEDURE RectPlusRect(operand1, operand2: Rect; VAR result: Rect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.left := operand1.left + operand2.left;
    result.top := operand1.top + operand2.top;
    result.right := operand1.right + operand2.right;
    result.bottom := operand1.bottom + operand2.bottom;
END;


{$S SgDRWres}
PROCEDURE RectMinusRect(operand1, operand2: Rect; VAR result: Rect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.left := operand1.left - operand2.left;
    result.top := operand1.top - operand2.top;
    result.right := operand1.right - operand2.right;
    result.bottom := operand1.bottom - operand2.bottom;
END;


{$IFC LibraryVersion <= 20}
{$S SgDRWres}
FUNCTION  EqualRect(rectA, rectB: Rect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    EqualRect := (rectA.left=rectB.left) AND (rectA.top=rectB.top) AND
                 (rectA.right=rectB.right) AND (rectA.bottom=rectB.bottom);
END;


{$S SgDRWres}
FUNCTION  EmptyRect(r: Rect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH r DO
        EmptyRect := (left >= right) OR (top >= bottom);
END;
{$ENDC}


{$S SgDRWres}
PROCEDURE AlignRect(VAR dstRect: Rect; srcRect: Rect; vhs: VHSelect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    dstRect.topLeft.vh[vhs] := srcRect.topLeft.vh[vhs];
    dstRect.botRight.vh[vhs] := srcRect.botRight.vh[vhs];
END;


{$S SgDRWres}
FUNCTION  LengthRect(r: Rect; vhs: VHSelect): INTEGER;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LengthRect := r.botRight.vh[vhs] - r.topLeft.vh[vhs];
END;


{$S SgDRWres}
FUNCTION  RectsNest(outer, inner: Rect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    RectsNest := RectHasPt(outer, inner.topLeft) AND RectHasPt(outer, inner.botRight);
END;


{$S SgDRWres}
FUNCTION  RectHasPt(dstRect: Rect; pt: Point): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    RectHasPt := (dstRect.left <= pt.h) AND (pt.h <= dstRect.right) AND
                 (dstRect.top <= pt.v) AND (pt.v <= dstRect.bottom);
END;


{$S SgDRWres}
PROCEDURE RectHavePt(dstRect: Rect; VAR pt: Point);
BEGIN {if dstRect is negative size, left/top is forced}
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    pt.h := Max(dstRect.left, Min(dstRect.right, pt.h));
    pt.v := Max(dstRect.top, Min(dstRect.bottom, pt.v));
END;


{$S SgDRWres}
PROCEDURE RectifyRect(VAR dstRect: Rect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    Pt2Rect(dstRect.topLeft, dstRect.botRight, dstRect);
END;


{$S SgDRWres}
FUNCTION  RectIsVisible(rectInPort: Rect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    RectIsVisible := RectInRgn(rectInPort, focusRgn);
END;


{$S SgABCdbg}
PROCEDURE PointToStr(pt: Point; str: TPstring);
    VAR s:  S255;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IntToStr(pt.h, str);
    IntToStr(pt.v, @s);
    str^ := CONCAT('(', str^, ',', s, ')');
END;


{$S SgABCdbg}
PROCEDURE RectToStr(r: Rect; str: TPstring);
    VAR s:  S255;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    PointToStr(r.topLeft, str);
    PointToStr(r.botRight, @s);
    str^ := CONCAT('[', str^, ',', s, ']');
END;
{$S SgDRWres}


{$S SgDRWres}
PROCEDURE LPtPlusLPt(operand1, operand2: LPoint; VAR result: LPoint);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h + operand2.h;
    result.v := operand1.v + operand2.v;
END;


{$S SgDRWres}
PROCEDURE LPtMinusLPt(operand1, operand2: LPoint; VAR result: LPoint);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h - operand2.h;
    result.v := operand1.v - operand2.v;
END;


{$S SgABCdat}
PROCEDURE LPtMulInt(operand1: LPoint; operand2: INTEGER; VAR result: LPoint);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := operand1.h * operand2;
    result.v := operand1.v * operand2;
END;


{$S SgABCdat}
PROCEDURE LPtDivInt(operand1: LPoint; operand2: INTEGER; VAR result: LPoint);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.h := LIntDivInt(operand1.h, operand2);
    result.v := LIntDivInt(operand1.v, operand2);
END;


{$S SgDRWres}
FUNCTION  EqualLPt(operand1, operand2: LPoint): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    EqualLPt := (operand1.h = operand2.h) AND (operand1.v = operand2.v);
END;


{$S SgDRWres}
PROCEDURE LRectPlusLRect(operand1, operand2: LRect; VAR result: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.left := operand1.left + operand2.left;
    result.top := operand1.top + operand2.top;
    result.right := operand1.right + operand2.right;
    result.bottom := operand1.bottom + operand2.bottom;
END;


{$S SgDRWres}
PROCEDURE LRectMinusLRect(operand1, operand2: LRect; VAR result: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    result.left := operand1.left - operand2.left;
    result.top := operand1.top - operand2.top;
    result.right := operand1.right - operand2.right;
    result.bottom := operand1.bottom - operand2.bottom;
END;


{$S SgDRWres}
FUNCTION  EqualLRect(rectA, rectB: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    EqualLRect := (rectA.left=rectB.left) AND (rectA.top=rectB.top) AND
                  (rectA.right=rectB.right) AND (rectA.bottom=rectB.bottom);
END;


{$S SgDRWres}
FUNCTION  EmptyLRect(r: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH r DO
        EmptyLRect := (left >= right) OR (top >= bottom);
END;


{$S SgDRWres}
PROCEDURE AlignLRect(VAR destLRect: LRect; srcLRect: LRect; vhs: VHSelect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    destLRect.topLeft.vh[vhs] := srcLRect.topLeft.vh[vhs];
    destLRect.botRight.vh[vhs] := srcLRect.botRight.vh[vhs];
END;


{$S SgDRWres}
FUNCTION  LengthLRect(r: LRect; vhs: VHSelect): LONGINT;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LengthLRect := r.botRight.vh[vhs] - r.topLeft.vh[vhs];
END;


{$S SgDRWres}
FUNCTION  LRectsNest(outer, inner: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LRectsNest := LRectHasLPt(outer, inner.topLeft) AND LRectHasLPt(outer, inner.botRight);
END;


{$S SgDRWres}
FUNCTION  LRectHasLPt(destLRect: LRect; pt: LPoint): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LRectHasLPt := (destLRect.left <= pt.h) AND (pt.h <= destLRect.right) AND
                   (destLRect.top <= pt.v) AND (pt.v <= destLRect.bottom);
END;


{$S SgDRWres}
PROCEDURE LRectHaveLPt(destLRect: LRect; VAR pt: LPoint);
BEGIN {if destLRect is negative size, left/top is forced}
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    pt.h := Max(destLRect.left, Min(destLRect.right, pt.h));
    pt.v := Max(destLRect.top, Min(destLRect.bottom, pt.v));
END;


{$S SgDRWres}
PROCEDURE RectifyLRect(VAR destLRect: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    SetLRect(destLRect, Min(destLRect.left, destLRect.right), Min(destLRect.top, destLRect.bottom),
                        Max(destLRect.left, destLRect.right), Max(destLRect.top, destLRect.bottom));
END;


{$S SgDRWres}
FUNCTION  LRectIsVisible(srcLRect: LRect): BOOLEAN;
    VAR rectInPort: Rect;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    thePad.LRectToRect(srcLRect, rectInPort);
    IF EmptyRect(rectInPort) THEN
        LRectIsVisible := FALSE
    ELSE
        LRectIsVisible := RectInRgn(rectInPort, focusRgn);
END;


{$S SgABCdbg}
PROCEDURE LPointToStr(pt: LPoint; str: TPstring);
    VAR s:  S255;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LIntToStr(pt.h, str);
    LIntToStr(pt.v, @s);
    str^ := CONCAT('(', str^, ',', s, ')');
END;


{$S SgABCdbg}
PROCEDURE LRectToStr(r: LRect; str: TPstring);
    VAR s:  S255;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LPointToStr(r.topLeft, str);
    LPointToStr(r.botRight, @s);
    str^ := CONCAT('[', str^, ',', s, ']');
END;
{$S SgDRWres}


{$S SgDRWres}
PROCEDURE SetLPt(VAR destPt: LPoint; itsH, itsV: LONGINT);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH destPt DO
        BEGIN
        h := itsH;
        v := itsV;
        END;
END;


{$S SgDRWres}
PROCEDURE SetLRect(VAR dstRect: LRect; itsLeft, itsTop, itsRight, itsBottom: LONGINT);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH dstRect DO
        BEGIN
        left := itsLeft;
        top := itsTop;
        right := itsRight;
        bottom := itsBottom;
        END;
END;


{$S SgDRWres}
PROCEDURE OffsetLRect(VAR dstRect: LRect; dh, dv: LONGINT);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH dstRect DO
        BEGIN
        left := left + dh;
        top := top + dv;
        right := right + dh;
        bottom := bottom + dv;
        END;
END;


{$S SgDRWres}
PROCEDURE InsetLRect(VAR dstRect: LRect; dh, dv: LONGINT);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH dstRect DO
        BEGIN
        left := left + dh;
        top := top + dv;
        right := right - dh;
        bottom := bottom - dv;
        IF (left >= right) OR (top >= bottom) THEN
            BEGIN
            left := 0;
            top := 0;
            right := 0;
            bottom := 0;
            END;
        END;
END;


{$S SgABCres}
FUNCTION  SectLRect(srcRectA, srcRectB: LRect; VAR dstRect: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH dstRect DO
        BEGIN
        left := Max(srcRectA.left, srcRectB.left);
        top := Max(srcRectA.top, srcRectB.top);
        right := Min(srcRectA.right, srcRectB.right);
        bottom := Min(srcRectA.bottom, srcRectB.bottom);
        IF (left >= right) OR (top >= bottom) THEN
            BEGIN
            SectLRect := FALSE;
            left := 0;
            top := 0;
            right := 0;
            bottom := 0;
            END
        ELSE
            SectLRect := TRUE;
        END;
END;


{$S SgDRWres}
PROCEDURE UnionLRect(srcRectA, srcRectB: LRect; VAR dstRect: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    WITH dstRect DO
        BEGIN
        left := Min(srcRectA.left, srcRectB.left);
        top := Min(srcRectA.top, srcRectB.top);
        right := Max(srcRectA.right, srcRectB.right);
        bottom := Max(srcRectA.bottom, srcRectB.bottom);
        END;
END;


{$S SgDRWres}
FUNCTION  LPtInLRect(pt: LPoint; r: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    LPtInLRect := (r.left <= pt.h) AND (pt.h < r.right) AND
                  (r.top <= pt.v) AND (pt.v < r.bottom);
END;


{$S SgABCdat}
FUNCTION  IsSmallPt(srcPt: LPoint): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IsSmallPt := (ABS(srcPt.h) < MAXINT) AND (ABS(srcPt.v) < MAXINT);
END;


{$S SgABCdat}
FUNCTION  IsSmallRect(srcRect: LRect): BOOLEAN;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IsSmallRect := IsSmallPt(srcRect.topLeft) AND IsSmallPt(srcRect.botRight);
END;


{Drawing Text}

{$S SgABCdat}
PROCEDURE DrawLText(textBuf: Ptr; startByte, numBytes: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
   {$IFC libraryVersion > 20}
    IF thePad.scaled THEN
        thePad.DrawLText(textBuf, startByte, numBytes)
    ELSE
        DrawText(QDPtr(textBuf), startByte, numBytes);
   {$ELSEC}
    DrawText(WordPtr(textBuf), startByte, numBytes);
   {$ENDC}
END;


{Drawing lines, rectangles, and ovals}

{$S SgDRWres}
PROCEDURE MoveToL(h, v: LONGINT);
VAR lPtInView:  LPoint;
    ptInPort:   Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     SetLPt(lPtInView, h, v);
     thePad.LPtToPt(lPtInView, ptInPort);
     MoveTo(ptInPort.h, ptInPort.v);
END;


{$S SgDRWres}
PROCEDURE MoveL(dh, dv: LONGINT);
VAR lPtInView:  LPoint;
    ptInPort:   Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     SetLPt(lPtInView, dh, dv);
     thePad.LDistToDist(lPtInView, ptInPort);
     Move(ptInPort.h, ptInPort.v);
END;


{$S SgDRWres}
PROCEDURE LineToL(h, v: LONGINT);
VAR lPtInView:	   LPoint;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     SetLPt(lPtInView, h, v);
     thePad.DrawLLine(lPtInView);
END;


{$S SgDRWres}
PROCEDURE LineL(dh, dv: LONGINT);
VAR lPtInView:  LPoint;
    ptInPort:   Point;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     SetLPt(lPtInView, dh, dv);
     thePad.LDistToDist(lPtInView, ptInPort);
     Line(ptInPort.h, ptInPort.v);
END;


{$S SgDRWres}
PROCEDURE FrameLRect(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRect(frame, r);
END;


{$S SgDRWres}
PROCEDURE PaintLRect(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRect(paint, r);
END;


{$S SgDRWres}
PROCEDURE EraseLRect(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRect(erase, r);
END;


{$S SgDRWres}
PROCEDURE InvrtLRect(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRect(invert, r);
END;


{$S SgDRWres}
PROCEDURE FillLRect(r: LRect; lPat: LPattern);
    VAR pat:    Pattern;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF amPrinting THEN
        thePad.LPatToPat(lPat, pat);
{$IFC LibraryVersion <= 20}
     thePat :=  Pattern(lPat);
{$ELSEC}
     thePort^.fillPat :=  Pattern(lPat);
{$ENDC}
     thePad.DrawLRect(fill, r);
END;


{$S SgDRWres}
PROCEDURE FrameLOval(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLOval(frame, r);
END;


{$S SgDRWres}
PROCEDURE PaintLOval(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLOval(paint, r);
END;


{$S SgDRWres}
PROCEDURE EraseLOval(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLOval(erase, r);
END;


{$S SgDRWres}
PROCEDURE InvrtLOval(r: LRect);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLOval(invert, r);
END;


{$S SgDRWres}
PROCEDURE FillLOval(r: LRect; lPat: LPattern);
    VAR pat:    Pattern;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF amPrinting THEN
        thePad.LPatToPat(lPat, pat);
{$IFC LibraryVersion <= 20}
     thePat :=  Pattern(lPat);
{$ELSEC}
     thePort^.fillPat :=  Pattern(lPat);
{$ENDC}
     thePad.DrawLOval(fill, r);
END;


PROCEDURE FrameLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRRect(frame, r, ovalWidth, ovalHeight);
END;


PROCEDURE PaintLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRRect(paint, r, ovalWidth, ovalHeight);
END;


PROCEDURE EraseLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRRect(erase, r, ovalWidth, ovalHeight);
END;


PROCEDURE InvrtLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLRRect(invert, r, ovalWidth, ovalHeight);
END;


PROCEDURE FillLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER; lPat: LPattern);
    VAR pat:    Pattern;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF amPrinting THEN
        thePad.LPatToPat(lPat, pat);
{$IFC LibraryVersion <= 20}
     thePat :=  Pattern(lPat);
{$ELSEC}
     thePort^.fillPat :=  Pattern(lPat);
{$ENDC}
     thePad.DrawLRRect(fill, r, ovalWidth, ovalHeight)
END;


PROCEDURE FrameLArc(r: LRect; startAngle, arcAngle: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLArc(frame, r, startAngle, arcAngle);
END;


PROCEDURE PaintLArc(r: LRect; startAngle, arcAngle: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLArc(paint, r, startAngle, arcAngle);
END;


PROCEDURE EraseLArc(r: LRect; startAngle, arcAngle: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLArc(erase, r, startAngle, arcAngle);
END;


PROCEDURE InvrtLArc(r: LRect; startAngle, arcAngle: INTEGER);
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
     thePad.DrawLArc(invert, r, startAngle, arcAngle);
END;


PROCEDURE FillLArc(r: LRect; startAngle, arcAngle: INTEGER; lPat: LPattern);
    VAR pat:    Pattern;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF amPrinting THEN
        thePad.LPatToPat(lPat, pat);
{$IFC LibraryVersion <= 20}
     thePat :=  Pattern(lPat);
{$ELSEC}
     thePort^.fillPat :=  Pattern(lPat);
{$ENDC}
     thePad.DrawLArc(fill, r, startAngle, arcAngle);
END;


PROCEDURE RotatePattern(pInPat, pOutPat: Ptr; dh, dv: LONGINT);
    EXTERNAL;


{$S SgABCdat}
FUNCTION  ClonePicture(pic: PicHandle; toHeap: THeap): PicHandle;
    VAR h:  TH;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    h := HAllocate(THz(toHeap), pic^^.picSize);
    XferLeft(Ptr(pic^), Ptr(h^), pic^^.picSize);
    ClonePicture := PicHandle(h);
END;
{$S SgDRWres}


PROCEDURE ResizeFeedback(mousePt: Point; minPt, maxPt: Point; outerRect: Rect;
                          tabHeight, sbWidth, sbHeight: INTEGER; VAR newPt: Point);

    VAR rFrame:	    Rect;
        limitRect:  Rect;
        oldMousePt: Point;
        innerTop:   INTEGER;
        fTab:	    BOOLEAN;
        fHscroll:   BOOLEAN;
        fVScroll:   BOOLEAN;
        event:	    EventRecord;
        savePort:   GrafPtr;

    PROCEDURE InitXorFrame;
    BEGIN
        fTab := TRUE;
        fHScroll := TRUE;
        fVScroll := TRUE;

          { set up scroll bar and tab widths }
          { the +1 's are to account for enlarging rFrame by one pixel }
        IF sbWidth > 0 THEN
            sbWidth := sbWidth+1
        ELSE
            fVScroll := FALSE;

        IF sbHeight > 0 THEN
            sbHeight := sbHeight+1
        ELSE
            fHScroll := FALSE;

        IF tabHeight > 0 THEN
            tabHeight := tabHeight+1
        ELSE
            fTab := FALSE;

          { setup rFrame - the outer rect for XORing  }
        rFrame := outerRect;
        InsetRect(rFrame, -1, -1);

        limitRect.topLeft := minPt;
        limitRect.botRight := maxPt;

        IF fTab THEN innerTop := rFrame.top+tabHeight
        ELSE innerTop := rFrame.top;

          { Setup the pen }
        PenNormal;
        PenPat(gray);
        PenMode(notPatXor);
    END;

    PROCEDURE XorFrame;
    BEGIN
        rFrame.botRight := newPt;
        FrameRect(rFrame);
        IF fTab THEN
            BEGIN
            MoveTo(rFrame.left, innerTop);
            LineTo(rFrame.right-1, innerTop);
            END;
        IF fHScroll THEN
            BEGIN
            MoveTo(rFrame.left, newPt.v-sbHeight);
            LineTo(rFrame.right-1, newPt.v-sbHeight);
            END;
        IF fVScroll THEN
            BEGIN
            MoveTo(newPt.h - sbWidth, innerTop);
            LineTo(newPt.h - sbWidth, rFrame.bottom-1);
            END;
    END;


    PROCEDURE DoDragFrame;
        VAR nxtPt:   Point;
    BEGIN
        nxtPt := Point(FPtPlusPt(newPt, Point(FPtMinusPt(mousePt, oldMousePt))));
        RectHavePt(limitRect, nxtPt);
        mousePt := Point(FPtPlusPt(Point(FPtMinusPt(nxtPt, newPt)), oldMousePt));

        IF NOT EqualPt(nxtPt, newPt) THEN
            BEGIN
            XorFrame;  { hide old }
            newPt := nxtPt;
            XorFrame;  { draw new }
            END;
     END;

BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    InitXorFrame;  { sets rFrame }

    newPt := rFrame.botRight;
    XorFrame;

    oldMousePt := mousePt;
    WHILE StillDown DO
        BEGIN
        GetMouse(mousePt);
        DoDragFrame;
        oldMousePt := mousePt;
        END;

    IF PeekEvent(event) AND (event.what = buttonUp) THEN
        BEGIN
        GetPort(savePort);
        SetPort(event.who);
        mousePt := event.where;
        LocalToGlobal(mousePt);
        SetPort(savePort);
        GlobalToLocal(mousePt);
        END
    ELSE
        GetMouse(mousePt);

    DoDragFrame;

    XorFrame;	       { hide last }
    newPt.h := newPt.h - 1;
    newPt.v := newPt.v - 1;
END; { ResizeFeedback }


{$S SgABCres}
PROCEDURE PopFocus;
BEGIN
    {$IFC fTrace}BP(6);{$ENDC}
    SetEmptyRgn(padRgn); {To save memory space}
    focusArea := focusStack[focusStkPtr];
    thePad := NIL;
    IF focusArea <> NIL THEN
        focusArea.Focus;
    focusStkPtr := focusStkPtr - 1;
    {$IFC fTrace}EP;{$ENDC}
END;


{$S SgABCres}
PROCEDURE PushFocus;
BEGIN
    {$IFC fTrace}BP(6);{$ENDC}
    focusStkPtr := focusStkPtr + 1;
    focusStack[focusStkPtr] := focusArea;
    {$IFC fTrace}EP;{$ENDC}
END;


{$S SgDRWres}
PROCEDURE MakeTypeStyle{(itsFamily: INTEGER; itsSize: INTEGER; itsFaces: TSetEFace/Style;
            VAR typeStyle: TTypeStyle)};
BEGIN
    {$IFC fTrace}BP(11);{$ENDC}
    WITH typeStyle DO
        BEGIN
        onFaces := itsFaces;
        font.fontFamily := itsFamily;
        font.fontSize := itsSize;
        END;
    {$IFC fTrace}EP;{$ENDC}
END;


FUNCTION QDFontNumber{(typeStyle: TTypeStyle): INTEGER};
BEGIN
    {$IFC fTrace}BP(11);{$ENDC}
    WITH typeStyle.font DO
        IF fontFamily = famSystem THEN
            QDFontNumber := fIDSystem
        ELSE
            QDFontNumber := fontID[fontFamily, fontSize];
    {$IFC fTrace}EP;{$ENDC}
END;


PROCEDURE SetQDTypeStyle{(typeStyle: TTypeStyle)};
BEGIN
    {$IFC fTrace}BP(11);{$ENDC}
    TextFont(QDFontNumber(typeStyle));
    TextFace(typeStyle.onFaces);
    {$IFC fTrace}EP;{$ENDC}
END;


METHODS OF TArea;


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE TArea.Fields(PROCEDURE Field(nameAndType: S255));
    BEGIN
        Field('innerRect: Rect');
        Field('outerRect: Rect');
        Field('parentBranch: TBranchArea');
    END;
    {$S SgDRWres}
    {$ENDC}


    FUNCTION  TArea.ChildWithPt(pt: Point; childList: TList; VAR nearestPt: Point): TArea;
        VAR foundArea:  TArea;
            s:	        TListScanner;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        RectHavePt(SELF.innerRect, pt);
        s := childList.scanner;
        WHILE s.Scan(foundArea) DO
            IF RectHasPt(foundArea.outerRect, pt) THEN
                s.Done;
        IF foundArea = NIL THEN
            BEGIN
            {$IFC fDbgDraw}
            ABCbreak('ChildWithPt found no area', 0);
            {$ENDC}
            foundArea := TArea(childList.First);
            END;
        RectHavePt(foundArea.innerRect, pt);
        nearestPt := pt;
        ChildWithPt := foundArea;
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TArea.Erase;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        FillRect(SELF.innerRect, white);
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TArea.Frame;
        VAR innerRect:	      Rect;
            borderRect:	    Rect;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        innerRect := SELF.innerRect;
        IF NOT RectsNest(innerRect, focusRgn^^.rgnBBox) THEN
            BEGIN
            PenNormal;
            PenSize(1, 1);
            borderRect := innerRect;
            InsetRect(borderRect, -1, -1);
            FrameRect(borderRect);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TArea.GetBorder(VAR border: Rect);
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        SetRect(border, -1, -1, 1, 1);
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TArea.SetInnerRect(newInnerRect: Rect);
        VAR border: Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.innerRect := newInnerRect;
        SELF.GetBorder(border);
  {$H-} RectPlusRect(SELF.innerRect, border, SELF.outerRect); {$H+}
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TArea.SetOuterRect(newOuterRect: Rect);
        VAR border: Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.outerRect := newOuterRect;
        SELF.GetBorder(border);
  {$H-} RectMinusRect(SELF.outerRect, border, SELF.innerRect); {$H+}
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S SgABCini}
BEGIN
        fontID[famModern, size20Pitch] := fID20Pitch;
        fontID[famModern, size15Pitch] := fID15Pitch;
        fontID[famModern, size10Pitch] := fIDm10Pitch;
        fontID[famModern, size12Pitch] := fIDm12Pitch;
        fontID[famModern, size12Point] := fIDm12Point;
        fontID[famModern, size14Point] := fIDm14Point;
        fontID[famModern, size18Point] := fIDm18Point;
        fontID[famModern, size24Point] := fIDm24Point;

        fontID[famClassic, size20Pitch] := fID20Pitch;
        fontID[famClassic, size15Pitch] := fID15Pitch;
        fontID[famClassic, size10Pitch] := fIDc10Pitch;
        fontID[famClassic, size12Pitch] := fIDc12Pitch;
        fontID[famClassic, size12Point] := fIDc12Point;
        fontID[famClassic, size14Point] := fIDc14Point;
        fontID[famClassic, size18Point] := fIDc18Point;
        fontID[famClassic, size24Point] := fIDc24Point;

        MakeTypeStyle(famSystem, 0 {dummy}, [], sysTypeStyle);
END;
{$S SgDRWres}


METHODS OF TPad;


    {$S sCldInit}
    FUNCTION  TPad.CREATE(object: TObject; heap: THeap; itsInnerRect: Rect; itsViewedLRect: LRect;
                        itsPadRes, itsViewRes: Point;
                        itsPort: GrafPtr): TPad;
        VAR zoomFactor: TScaler;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TPad(object);
        SELF.parentBranch := NIL;
        SetPt(zoomFactor.numerator, 1, 1);
        SetPt(zoomFactor.denominator, 1, 1);
        SELF.Redefine(itsInnerRect, itsViewedLRect, itsPadRes, itsViewRes,
                      zoomFactor, itsPort);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S sCldInit}
    PROCEDURE TPad.Redefine(itsInnerRect: Rect; itsViewedLRect: LRect;
                     itsPadRes, itsViewRes: Point;
                     itsZoomFactor: TScaler; itsPort: GrafPtr);
        VAR vhs:        VHSelect;
            newOffset:  LPoint;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.SetInnerRect(itsInnerRect);
        WITH SELF, scaleFactor DO
     {$H-}  BEGIN
            port := itsPort;
            viewedLRect := itsViewedLRect;
            availLRect := itsViewedLRect;
            InsetLRect(availLRect, -8192, -8192);
            clippedRect := itsInnerRect;
            zoomFactor := itsZoomFactor;

           {install new Resolutions}
            padRes := itsPadRes;
            viewedRes := itsViewRes;

           {compute scale factor from resolutions and zoom factor}
            FOR vhs := v TO h DO
                BEGIN
                numerator.vh[vhs]   := itsPadRes.vh[vhs] * zoomFactor.numerator.vh[vhs];
                denominator.vh[vhs] := itsViewRes.vh[vhs] * zoomFactor.denominator.vh[vhs];
                Reduce(numerator.vh[vhs], denominator.vh[vhs]);
                END;

            scaled := (numerator.h <> denominator.h) OR (numerator.v <> denominator.v);

           {compute scroll offset}

            FOR vhs := v TO h DO
                newOffset.vh[vhs] :=
                 LIntOvrInt(LIntMulInt(itsViewedLRect.topLeft.vh[vhs],
                                       numerator.vh[vhs]),
                            denominator.vh[vhs]) - itsInnerRect.topLeft.vh[vhs];

            SELF.SetScrollOffset(newOffset);
     {$H+}  END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE TPad.Fields(PROCEDURE Field(nameAndType: S255));
    BEGIN
        TArea.Fields(Field);
        Field('port: Ptr');
        Field('viewedLRect: LRect');
        Field('visLRect: LRect');
        Field('availLRect: LRect');
        Field('scrollOffset: LPoint');
        Field('origin: Point'); {+LSR+}
        Field('cdOffset: LPoint'); {+LSR+}
        Field('clippedRect: rect');
        Field('padRes: Point');
        Field('viewedRes: Point');
        Field('scaled: BOOLEAN');
        Field('scaleFactor: RECORD numerator: Point; denominator: Point END');
        Field('zoomFactor: RECORD numerator: Point; denominator: Point END');
    END;
    {$S SgDRWres}
    {$ENDC}


    PROCEDURE TPad.ClipFurtherTo(rBand: rect);  {narrows down clip area at next Focus}
        VAR grafRect: Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
   {$H-} IF SectRect(rBand, SELF.clippedRect, SELF.clippedRect) THEN; {$H+}
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.DistToLDist(distInPort: Point; VAR lDistInView: LPoint);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF SELF.scaled THEN
            WITH SELF.scaleFactor DO
          {$H-} BEGIN
                lDistInView.h := LIntOvrInt(LIntMulInt(distInPort.h, denominator.h), numerator.h);
                lDistInView.v := LIntOvrInt(LIntMulInt(distInPort.v, denominator.v), numerator.v);
          {$H+} END
        ELSE
            BEGIN
            lDistInView.h := distInPort.h;
            lDistInView.v := distInPort.v;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.DrawLLine(newLPt: LPoint);
    VAR newGrafPt: Point;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LPtToPt(newLPt, newGrafPt);
        StdLine(newGrafPt);
    END;


{$IFC LibraryVersion <= 20}
{This is still not the right implementation when we are printing}
    PROCEDURE TPad.DrawLPicture(pic: PicHandle; r:LRect);
        VAR rectInPort: Rect;
    BEGIN
        SELF.LRectToRect(r, rectInPort);
        DrawPicture(pic, rectInPort);
    END;
{$ELSEC}
    PROCEDURE TKStdText(byteCount: INTEGER; textBuf: QDPtr; numer, denom: Point);
    BEGIN
        StdText(byteCount, textBuf, numer, numer);
    END;

    PROCEDURE TKStdComment(kind, datasize: INTEGER; dataHandle: QDHandle);
    CONST
        picForeColor    =   108;
        picBackColor    =   109;

    VAR pData:  TpLongint;

    BEGIN
        IF dataHandle <> NIL THEN
            IF dataSize <> 4 THEN
                BEGIN
                pData := TpLongint(ORD(dataHandle^));

                CASE kind OF
                    picForeColor:
                        ForeColor(pData^);
                    picBackColor:
                        BackColor(pData^);
                    END;
                END;
    END;

{This is still not the right implementation when we are printing}
    PROCEDURE TPad.DrawLPicture(pic: PicHandle; r:LRect);
        VAR rectInPort:	    Rect;
            oldProcsPtr:    QDProcsPtr;
            TKProcs:	    QDProcs;
            oldTextProc:    QDPtr;
            oldCommentProc: QDPtr;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        WITH thePort^ DO
            BEGIN
            oldProcsPtr := grafprocs;
            IF oldProcsPtr = NIL THEN
                BEGIN
                SetStdProcs(TKProcs);
                grafprocs := @TKProcs;
                END;
            WITH grafprocs^ DO
                BEGIN
                oldTextProc := textProc;
                oldCommentProc := commentProc;
                IF amPrinting THEN
                    BEGIN
                    textProc := @TKStdText;
                    commentProc := @TKStdComment;
                    END;
                END;
            END;

        SELF.LRectToRect(r, rectInPort);
        DrawPicture(pic, rectInPort);

        WITH thePort^ DO
            BEGIN
            IF oldProcsPtr <> NIL THEN
                WITH grafprocs^ DO
                    BEGIN
                    textProcs := oldTextProc;
                    commentProc := oldCommentProc;
                    END;
            grafProcs := oldProcsPtr;
            END;
    END;
{$ENDC}


    PROCEDURE TPad.DrawLRect(verb: GrafVerb; r: LRect);
    VAR rectInPort: Rect;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LRectToRect(r, rectInPort);
        StdRect(verb, rectInPort);
    END;


    PROCEDURE TPad.DrawLRRect(verb: GrafVerb; r: LRect; ovalWidth, ovalHeight: INTEGER);
    VAR rectInPort: Rect;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LRectToRect(r, rectInPort);
        StdRRect(verb, rectInPort, ovalWidth, ovalHeight);
    END;


    PROCEDURE TPad.DrawLOval(verb: GrafVerb; r: LRect);
    VAR rectInPort: Rect;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LRectToRect(r, rectInPort);
        StdOval(verb, rectInPort);
    END;


    PROCEDURE TPad.DrawLArc(verb: GrafVerb; r: LRect; startAngle, arcAngle: INTEGER);
    VAR rectInPort: Rect;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LRectToRect(r, rectInPort);
        StdArc(verb, rectInPort, startAngle, arcAngle);
    END;


    PROCEDURE TPad.DrawLBits(VAR srcBits: BitMap; VAR srcRect: Rect;
                                VAR dstLRect: LRect; mode: INTEGER; maskRgn: RgnHandle);
    VAR dstGrafRect: Rect;
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        SELF.LRectToRect(dstLRect, dstGrafRect);
        StdBits(srcBits, srcRect,dstGrafRect, mode, maskRgn);
    END;


{$S SgABCres}
    PROCEDURE TPad.Focus;
        VAR visRgn: RgnHandle;
            origin: Point;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF SELF.Port <> printerPseudoPort THEN
            SetPort(SELF.port);	  {for the moment anyway don't tamper if being controlled by LisaPrint}

        SetOrigin(0, 0);    {so thePort^.visRgn will be relative to a (0,0)-origined space, to match
                                SELF.clippedRect and altVisRgn}

        RectRgn(padRgn, SELF.clippedRect);

        IF useAltVisRgn THEN
            visRgn := altVisRgn	      {Instigated by TWindow.StashPicture or TClipboard.Publicize}
        ELSE
            visRgn := thePort^.visRgn;

        SectRgn(padRgn, visRgn, padRgn);

        origin := SELF.origin;
        WITH origin DO {+LSR+}
            BEGIN
            SetOrigin(h, v);
            OffsetRgn(padRgn, h, v);
            END;

        SetClip(padRgn);
        focusRgn := padRgn;  {focusRgn is an alias for either padRgn or visRgn}

        focusArea := SELF;
        thePad := SELF;

        WITH SELF DO
      {$H-} BEGIN
            SELF.RectToLRect(focusRgn^^.rgnBBox, visLRect);
            IF SectLRect(viewedLRect, visLRect, visLRect) THEN
                BEGIN END;
      {$H+} END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.InvalLRect(r: LRect);
        VAR rectInPort: Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.LRectToRect(r, rectInPort);
        SELF.InvalRect(rectInPort);
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.InvalRect(r: Rect);
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SectRect(r, focusRgn^^.rgnBBox, r) THEN
            InvalRect(r);
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgDRWres}


    PROCEDURE TPad.LDistToDist(lDistInView: LPoint; VAR distInPort: Point);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF SELF.scaled THEN
            WITH SELF.scaleFactor DO
          {$H-} BEGIN
                distInPort.h := LIntOvrInt(LIntMulInt(lDistInView.h, numerator.h), denominator.h);
                distInPort.v := LIntOvrInt(LIntMulInt(lDistInView.v, numerator.v), denominator.v);
          {$H+} END
        ELSE
            BEGIN
            distInPort.h := lDistInView.h;
            distInPort.v := lDistInView.v;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.LPatToPat(lPatInView: LPattern; VAR patInPort: Pattern);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF amPrinting THEN
            RotatePattern(@lPatInView, @patInPort, SELF.cdOffset.h, SELF.cdOffset.v)
        ELSE
            patInPort := Pattern(lPatInView); {+LSR+}
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.LPtToPt(lPtInView: LPoint; VAR ptInPort: Point);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        LRectHaveLPt(SELF.availLRect, lPtInView);
        WITH SELF, cdOffset, scaleFactor DO {+LSR+}
            IF scaled THEN
          {$H-} BEGIN
                ptInPort.h := LIntOvrInt(LIntMulInt(lPtInView.h, numerator.h), denominator.h) - h;
                ptInPort.v := LIntOvrInt(LIntMulInt(lPtInView.v, numerator.v), denominator.v) - v;
          {$H+} END
            ELSE
                BEGIN
                ptInPort.h := lPtInView.h - h;
                ptInPort.v := lPtInView.v - v;
                END;
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S SgABCres}
    PROCEDURE TPad.LRectToRect(lRectInView: LRect; VAR rectInPort: Rect);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        LRectHaveLPt(SELF.availLRect, lRectInView.topLeft);
        LRectHaveLPt(SELF.availLRect, lRectInView.botRight);
        WITH SELF, cdOffset, scaleFactor DO {+LSR+}
            IF scaled THEN
          {$H-} BEGIN
                rectInPort.left := LIntOvrInt(LIntMulInt(lRectInView.left, numerator.h), denominator.h) - h;
                rectInPort.top := LIntOvrInt(LIntMulInt(lRectInView.top, numerator.v), denominator.v) - v;
                rectInPort.right := LIntOvrInt(LIntMulInt(lRectInView.right, numerator.h), denominator.h) - h;
                rectInPort.bottom := LIntOvrInt(LIntMulInt(lRectInView.bottom, numerator.v), denominator.v)
                                     - v;
          {$H+} END
            ELSE
                BEGIN
                rectInPort.left := lRectInView.left - h;
                rectInPort.top := lRectInView.top - v;
                rectInPort.right := lRectInView.right - h;
                rectInPort.bottom := lRectInView.bottom - v;
                END;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgDRWres}


    PROCEDURE TPad.OffsetBy(deltaLPt: LPoint);
        VAR vhs:        VHSelect;
            newOffset:  LPoint;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        WITH SELF, deltaLPt DO
      {$H-} BEGIN
            OffsetLRect(viewedLRect, h, v);
            OffsetLRect(availLRect, h, v);
      {$H+} END;

        FOR vhs := v TO h DO {$H-} {+LSR+}
            WITH SELF, scaleFactor DO
                newOffset.vh[vhs] := LIntOvrInt(LIntMulInt(viewedLRect.topLeft.vh[vhs],
                                                              numerator.vh[vhs]),
                                                   denominator.vh[vhs]) - innerRect.topLeft.vh[vhs];
        {$H+}
        SELF.SetScrollOffset(newOffset);
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.PatToLPat(patInPort: Pattern; VAR lPatInView: LPattern);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF amPrinting THEN
            RotatePattern(@patInPort, @lPatInView, -SELF.cdOffset.h, -SELF.cdOffset.v)
        ELSE
            LPatInView := LPattern(patInPort); {+LSR+}
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.PtToLPt(ptInPort: Point; VAR lPtInView: LPoint);
    {$IFC fDbgDraw}
    VAR pt: Point;
        s:  S255;
    {$ENDC}
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        WITH SELF, cdOffset, scaleFactor DO {+LSR+}
            IF scaled THEN
          {$H-} BEGIN
                lPtInView.h := LIntOvrInt(LIntMulInt(ptInPort.h + h, denominator.h), numerator.h);
                lPtInView.v := LIntOvrInt(LIntMulInt(ptInPort.v + v, denominator.v), numerator.v);
          {$H+} END
        ELSE
            BEGIN
            lPtInView.h := ptInPort.h + h;
            lPtInView.v := ptInPort.v + v;
            END;
        {$IFC fDbgDraw}
        SELF.LPtToPt(lPtInView, pt);
        IF NOT EqualPt(pt, ptInPort) THEN
            BEGIN
            PointToStr(ptInPort, @s);
            writeln('ptInPort:', s);
            LPointToStr(lPtInView, @s);
            writeln('lPtInView:',s);
            PointToStr(pt, @s);
            writeln('pt:', s);
            WrObj(SELF, 1, '');
            writeln;
            ABCbreak('Error in TPad.PtToLPt', 0);
            END;
        {$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S SgABCres}
    PROCEDURE TPad.RectToLRect(rectInPort: Rect; VAR lRectInView: LRect);
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        WITH SELF, cdOffset, scaleFactor DO {+LSR+}
            IF scaled THEN
          {$H-} BEGIN
                lRectInView.left :=
                    LIntOvrInt(LIntMulInt(rectInPort.left + h, denominator.h), numerator.h);
                lRectInView.top :=
                    LIntOvrInt(LIntMulInt(rectInPort.top + v, denominator.v), numerator.v);
                lRectInView.right :=
                    LIntOvrInt(LIntMulInt(rectInPort.right + h, denominator.h), numerator.h);
                lRectInView.bottom :=
                    LIntOvrInt(LIntMulInt(rectInPort.bottom + v, denominator.v), numerator.v);
          {$H+} END
        ELSE
            BEGIN
            lRectInView.left := rectInPort.left + h;
            lRectInView.top := rectInPort.top + v;
            lRectInView.right := rectInPort.right + h;
            lRectInView.bottom := rectInPort.bottom + v;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgDRWres}


    PROCEDURE TPad.SetPen(pen: PenState);
        VAR  lPat:   LPattern;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF amPrinting THEN
            BEGIN
            noPad.PatToLPat(pen.pnPat, lPat);
            SELF.LPatToPat(lPat, pen.pnPat);
            END;
        SetPenState(pen);
        {$IFC fTrace}EP;{$ENDC}
    END;



    PROCEDURE TPad.SetPenToHighlight(highTransit: THighTransit);
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.SetPen(highPen[highTransit]);
        {$IFC fTrace}EP;{$ENDC}
    END;


    PROCEDURE TPad.SetScrollOffset(VAR newOffset: LPoint);
                        {recalculates the origin and cdOffset fields; does not change arg}
        VAR vhs:    VHSelect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        WITH SELF DO
            BEGIN
            scrollOffset := newOffset;

            FOR vhs := v TO h DO
                BEGIN
                origin.vh[vhs] := newOffset.vh[vhs] MOD magicNumber;
                cdOffset.vh[vhs] := newOffset.vh[vhs] - origin.vh[vhs];
                END;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S Override}
    PROCEDURE TPad.SetZoomFactor; {.... ONLY SEEMS TO BE RELEVANT FOR PANE--NONSENSE HERE FOR NOW}
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S SgABCdat}
    PROCEDURE TPad.DrawLText(textBuf: Ptr; startByte, numBytes: INTEGER);
    BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
        WITH SELF.zoomFactor DO {$H-}
   {$IFC libraryVersion > 20}
            StdText(numBytes, QDPtr(ORD(textBuf) + startByte), numerator, denominator);
   {$ELSEC}
            DrawText(WordPtr(textBuf), startByte, numBytes);
   {$ENDC}  {$H+}
    END;
{$S SgDRWres}

{$S SgABCini}
BEGIN

    UnitAuthor('Apple');
    printerPseudoPort := POINTER(0);
    crashPad := NIL;
    SetPt(screenRes, 90, 60);

    lPatWhite  := LPattern(white);
    lPatBlack  := LPattern(black);
    lPatGray   := LPattern(gray);
    lPatLtGray := LPattern(ltGray);
    lPatDkGray := LPattern(dkGray);

    amPrinting := FALSE;
END;
{$S SgDRWres}


METHODS OF TBranchArea;


    {$S SgABCcld}
    FUNCTION  TBranchArea.CREATE(object: TObject; heap: THeap; vhs: VHSelect; hasElderFirst: BOOLEAN;
                                     whoCanResizeIt: TResizability;
                                     itsElderChild, itsYoungerChild: TArea): TBranchArea;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TBranchArea(object);

        WITH SELF DO
            BEGIN
            outerRect := itsElderChild.outerRect;
            parentBranch := itsElderChild.parentBranch;
            arrangement := vhs;
            elderFirst := hasElderFirst;
            resizability := whoCanResizeIt;
            elderChild := itsElderChild;
            youngerChild := itsYoungerChild;
            END;

        itsElderChild.parentBranch := SELF;
        itsYoungerChild.parentBranch := SELF;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE TBranchArea.Fields(PROCEDURE Field(nameAndType: S255));
    BEGIN
        TArea.Fields(Field);
        Field('arrangement: Byte');
        Field('elderFirst: BOOLEAN');
        Field('resizability: Byte');
        Field('elderChild: TArea');
        Field('youngerChild: TArea');
    END;
    {$S SgDRWres}
    {$ENDC}


    {$S SgABCcld}
    PROCEDURE TBranchArea.GetMinExtent(VAR minExtent: Point; windowIsResizingIt: BOOLEAN);
        VAR elderMinSize:   Point;
            youngerMinSize: Point;
            vhs:	    VHSelect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        vhs := SELF.arrangement;

        SELF.elderChild.GetMinExtent(elderMinSize, TRUE);
        SELF.youngerChild.GetMinExtent(youngerMinSize, TRUE);

        IF windowIsResizingIt AND NOT (windowCanResizeIt IN SELF.resizability) THEN
            youngerMinSize.vh[vhs] := LengthRect(SELF.youngerChild.outerRect, vhs);

        minExtent.vh[vhs] := elderMinSize.vh[vhs] + youngerMinSize.vh[vhs];

        vhs := orthogonal[vhs];
        minExtent.vh[vhs] := Max(elderMinSize.vh[vhs], youngerMinSize.vh[vhs]);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S SgABCcld}
    FUNCTION  TBranchArea.OtherChild(child: TArea): TArea;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF.elderChild = child THEN
            OtherChild := SELF.youngerChild
        ELSE
        {$IFC fDbgDraw}
        IF SELF.youngerChild = child THEN
            OtherChild := SELF.elderChild
        ELSE
            ABCBreak('This panel branch does not have a child that is', ORD(child));
        {$ELSEC}
            OtherChild := SELF.elderChild;
        {$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S SgABCcld}
    PROCEDURE TBranchArea.Redivide(newCd: INTEGER);
        VAR elderRect:	    Rect;
            youngerRect:    Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        elderRect := SELF.elderChild.outerRect;
        youngerRect := SELF.youngerChild.outerRect;

        TRectCoords(elderRect)[SELF.elderFirst].vh[SELF.arrangement] := newCd;
        TRectCoords(youngerRect)[NOT SELF.elderFirst].vh[SELF.arrangement] := newCd;

        SELF.elderChild.ResizeOutside(elderRect);
        SELF.youngerChild.ResizeOutside(youngerRect);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S SgABCcld}
    PROCEDURE TBranchArea.ReplaceChild(child, newChild: TArea);
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF.elderChild = child THEN
            SELF.elderChild := newChild
        ELSE
        {$IFC fDbgDraw}
        IF SELF.youngerChild = child THEN
            SELF.youngerChild := newChild
        ELSE
            ABCBreak('This panel branch does not have a child that is', ORD(child));
        {$ELSEC}
            SELF.youngerChild := newChild;
        {$ENDC}

        newChild.parentBranch := SELF;
        IF child.parentBranch = SELF THEN
            child.parentBranch := NIL;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S SgABCcld}
    PROCEDURE TBranchArea.ResizeOutside(newOuterRect: Rect);
        VAR formerRect:	    Rect;
            elderChild:	    TArea;
            youngerChild:   TArea;
            elderRect:	    Rect;
            youngerRect:    Rect;
            vhs:	    VHSelect;
            eldFirst:	    BOOLEAN;
            minExtents:	    ARRAY [FALSE..TRUE] OF Point;
            newCd:	    INTEGER;
            deltaRect:	    Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        formerRect := SELF.outerRect;

        elderChild := SELF.elderChild;
        youngerChild := SELF.youngerChild;

        elderRect := elderChild.outerRect;
        youngerRect := youngerChild.outerRect;

        vhs := SELF.arrangement;
        eldFirst := SELF.elderFirst;

        IF windowCanResizeIt IN SELF.resizability THEN
            BEGIN   {both children resize proportionally}
            MapRect(elderRect, formerRect, newOuterRect);
            MapRect(youngerRect, formerRect, newOuterRect);

            elderChild.GetMinExtent(minExtents[NOT eldFirst], TRUE);
            youngerChild.GetMinExtent(minExtents[eldFirst], TRUE);

            IF (minExtents[FALSE].vh[vhs] + minExtents[TRUE].vh[vhs]) < LengthRect(newOuterRect, vhs) THEN
                BEGIN   {It is possible to satisfy both min constraints, so do so}
                newCd := Max(newOuterRect.topLeft.vh[vhs] + minExtents[FALSE].vh[vhs],
                             Min(newOuterRect.botRight.vh[vhs] - minExtents[TRUE].vh[vhs],
                                 TRectCoords(elderRect)[eldFirst].vh[vhs]));
                TRectCoords(elderRect)[eldFirst].vh[vhs] := newCd;
                TRectCoords(youngerRect)[NOT eldFirst].vh[vhs] := newCd;
                END;
            END

        ELSE
            BEGIN   {only elder child resizes in my direction}
            RectMinusRect(newOuterRect, formerRect, deltaRect);
            RectPlusRect(elderRect, deltaRect, elderRect);

            TRectCoords(deltaRect)[NOT eldFirst].vh[vhs] := TRectCoords(deltaRect)[eldFirst].vh[vhs];
            RectPlusRect(youngerRect, deltaRect, youngerRect);
            END;

        youngerChild.ResizeOutside(youngerRect);
        elderChild.ResizeOutside(elderRect);
        SELF.outerRect := newOuterRect;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}


    {$S SgABCcld}
    FUNCTION  TBranchArea.TopLeftChild: TArea;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF.elderFirst THEN
            TopLeftChild := SELF.elderChild
        ELSE
            TopLeftChild := SELF.youngerChild;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgDRWres}

{$S SgABCini}
END;
{$S SgDRWres}
{$S SgABCini}



